<?php
namespace core\models;
/**
 * Url 处理
 * @package core\models
 * @author  ZhouHaoHua <53027327@qq.com>
 */
class Url {

    /**
     * 最终的URL地址
     * @var string
     */
    protected $page = '';

    /**
     * 需要去掉的参数
     * @var array
     */
    protected $remove_parameters = array('mod');


    /**
     * 传进来处理过后的参数数组
     * @var array
     */
    protected $params = array();

    /**
     * 需要转换的参数,生成URL时把val转化成key,还原时找key还原成值
     * @var array
     */
    protected $transform_parameters = array();

    /**
     * 参数分隔符
     * @var string
     */
    protected $separator = '/';

    /**
     * 默认的URL扩展名
     * @var string
     */
    protected $extension = '.html';
    /**
     * 控制器的代表参数名
     * @var string
     */
    protected $arg_controller_name;
    /**
     * 动作方法的代表参数名
     * @var string
     */
    protected $arg_action_name;

    /**
     * 其它没有自定义SEO规则时的页面URL处理
     * @param string $page                控制器文件名
     * @param string $params              GET参数串，如:a=9&b=10&arg=op
     * @param string $arg_controller_name 控制器的代表参数名，默认是mod
     * @param string $arg_action_name     动作方法的代表参数名，默认是action
     */
    public function __construct($page = '', $params = '', $arg_controller_name = 'mod', $arg_action_name = 'action') {
        $this->page                = $page . '/';
        $this->arg_controller_name = $arg_controller_name;
        $this->arg_action_name     = $arg_action_name;
        $this->remove_parameters   = array($this->arg_controller_name);

        parse_str($params, $params_arr);
        $params_arr[$this->arg_action_name] = (isset($params_arr[$this->arg_action_name]) ? $params_arr[$this->arg_action_name] : '');

        $params = http_build_query($params_arr);
        $this->parseParams($params);
    }

    /**
     * 拆分传进来的URL参数字符串
     * @param string $temp 传进来的参数字符串
     */
    protected function parseParams($temp) {
        $arr_temp = array();
        if ($temp) {
            parse_str($temp, $arr_temp);
        }
        $rtn = array();
        foreach ($arr_temp as $key => $val) {
            // 去掉参数中前面增加的MOD参数 $tmp[0] != 'mod'
            if (!in_array($key, $this->remove_parameters) && $val) {
                $rtn[arrays::strip_tags($key)] = arrays::strip_tags($val);
            }
        }
        $this->params = $rtn;
    }

    /**
     * 组合替换生成最终的URL形式
     */
    protected function combinationUrl() {
        $_action    = 'index';
        $_mod       = $this->page;
        $this->page = '';
        foreach ($this->params as $key => $val) {
            $skey   = array_search($key, $this->transform_parameters); // 查找需要转换掉的参数名称,
            $p_name = ($skey !== false) ? $skey : $key; // 如果找到，使用转换后的，否则保持不变
            if (is_array($val)) { // 如果值是一个数组, 需要做特殊处理
                foreach ($val as $k => $v) {
                    $this->page .= $p_name . '[' . $k . ']' . '-' . $v . $this->separator;
                }
            } elseif ($p_name == $this->arg_action_name) {  //【新】要把action参数提取出来，如果没有action那么它的值是index
                $_action = $val;
            } else {
                $this->page .= $p_name . '-' . $val . $this->separator;
            }
        }
        //根据有参数和无参数的情况来组织最后的页面
        if (sizeof($this->params)) {
            $this->page = trim($_mod, $this->separator) . $this->separator . $_action . $this->separator . trim($this->page, $this->separator);
        } else {
            $this->page = trim($_mod, $this->separator);
        }
    }

    /**
     * 取得生成的URL（有SEO）
     * @return string
     */
    public function getUrl() {
        $this->combinationUrl();
        return $this->page . (substr($this->page, -1) == '/' ? '' : $this->extension);
    }

    /**
     * 分析并还原URL为对应的原变量
     * @param string $url_str 这个值的格式与$_SERVER['REQUEST_URI']相同，若不传此值就默认取$_SERVER['REQUEST_URI']的值
     * @return bool 如果返回true就代表有404错误
     */
    public function parseUrl($url_str = null) {
        $url_str = ($url_str!==null) ? $url_str : $_SERVER['REQUEST_URI'];
        $tmp = explode('?', $url_str);
        $tmp[0] = strtr($tmp[0],['//'=>'/']);
        $_tmp = explode('/',$tmp[0]);
        if (strpos($_tmp[count($_tmp)-1],'.') === false) {
            if (substr($tmp[0], -1) !== '/') {
                $tmp[0] = $tmp[0] . '/';
            }
        }
        $url_str = implode('?', $tmp);
        $url_str = preg_replace('@^/@','',$url_str);
        // 检查是否有带参数
        $tmp = explode('?',$url_str);
        $url_str = preg_replace('@' . preg_quote($this->extension,'@') . '$@','',$tmp[0]);
        $error404                     = true;
        $url_arr                      = $url_str ? explode('/', urldecode($url_str)) : array();
        $_GET[$this->arg_action_name] = ($_GET[$this->arg_action_name] ? $_GET[$this->arg_action_name] : 'index');
        if ($this->separator == '/') {
            for ($i = 0, $n = sizeof($url_arr); $i < $n; $i++) {
                if(strpos($url_arr[$i], '?')!==false){
                    continue;
                }
                if ($i == 0 && $url_arr[$i]) {  //取mod
                    $_GET[$this->arg_controller_name] = $url_arr[$i];
                    if (file_exists(Z_APP . '/controllers/' . $_GET[$this->arg_controller_name] . '.php') || file_exists(Z_APP . '/controllers/' . str_replace(array('_', '-'), '/', $_GET[$this->arg_controller_name]) . '.php')) {
                        $error404 = false;
                    }
                } elseif ($i == 1 && $url_arr[$i]) {  //取action
                    $_GET[$this->arg_action_name] = $url_arr[$i];
                } elseif ($i >= 2 && $url_arr[$i]) {  //取其它参数
                    $tmp           = explode('-', $url_arr[$i], 2);
                    if($tmp[1]) {
                        $_GET[$tmp[0]] = $tmp[1];
                    }
                }
            }
        }
        return $error404;
    }
}
